home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / jpsrc2.zip / JVIRTMEM.C < prev    next >
C/C++ Source or Header  |  1991-12-02  |  20KB  |  615 lines

  1. /*
  2.  * jvirtmem.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file provides the system-dependent memory allocation routines
  9.  * for the case where we can rely on virtual memory to handle large arrays.
  10.  *
  11.  * This includes some MS-DOS code just for trial purposes; "big" arrays will
  12.  * have to be handled with temp files on MS-DOS, so a real implementation of
  13.  * a DOS memory manager will probably be a separate file.  (See additional
  14.  * comments about big arrays, below.)
  15.  * 
  16.  * NB: allocation routines never return NULL.
  17.  * They should exit to error_exit if unsuccessful.
  18.  */
  19.  
  20. #define AM_MEMORY_MANAGER    /* we define big_Xarray_control structs */
  21.  
  22. #include "jinclude.h"
  23.  
  24. #ifdef INCLUDES_ARE_ANSI
  25. #include <stdlib.h>        /* to declare malloc(), free() */
  26. #else
  27. extern void * malloc PP((size_t size));
  28. extern void free PP((void *ptr));
  29. #endif
  30.  
  31.  
  32. /* Insert system-specific definitions of far_malloc, far_free here. */
  33.  
  34. #ifndef NEED_FAR_POINTERS    /* Generic for non-braindamaged CPUs */
  35.  
  36. #define far_malloc(x)    malloc(x)
  37. #define far_free(x)    free(x)
  38.  
  39. #else /* NEED_FAR_POINTERS */
  40.  
  41. #ifdef __TURBOC__
  42. /* These definitions work for Turbo C */
  43. #include <alloc.h>        /* need farmalloc(), farfree() */
  44. #define far_malloc(x)    farmalloc(x)
  45. #define far_free(x)    farfree(x)
  46. #else
  47. #ifdef MSDOS
  48. /* These definitions work for Microsoft C and compatible compilers */
  49. #include <malloc.h>        /* need _fmalloc(), _ffree() */
  50. #define far_malloc(x)    _fmalloc(x)
  51. #define far_free(x)    _ffree(x)
  52. #endif
  53. #endif
  54.  
  55. #endif /* NEED_FAR_POINTERS */
  56.  
  57. /*
  58.  * When allocating 2-D arrays we can either ask malloc() for each row
  59.  * individually, or grab the whole space in one chunk.  The latter is
  60.  * a lot faster on large arrays, but fails if malloc can't handle big
  61.  * requests, as is typically true on MS-DOS.
  62.  * We assume here that big malloc requests are safe whenever
  63.  * NEED_FAR_POINTERS is not defined, but you can change this if you are
  64.  * on a weird machine.
  65.  */
  66.  
  67. #ifndef NEED_FAR_POINTERS
  68. #define BIG_MALLOCS_OK        /* safe to ask far_malloc for > 64Kb */
  69. #endif
  70.  
  71.  
  72. /*
  73.  * Some important notes:
  74.  *   The array alloc/dealloc routines are not merely a convenience;
  75.  *   on 80x86 machines the bottom-level pointers in an array are FAR
  76.  *   and thus may not be allocatable by alloc_small.
  77.  *
  78.  *   Also, it's not a good idea to try to merge the sarray and barray
  79.  *   routines, even though they are textually almost the same, because
  80.  *   samples are usually stored as bytes while coefficients are shorts.
  81.  *   Thus, in machines where byte pointers have a different representation
  82.  *   from word pointers, the resulting machine code could not be the same.
  83.  */
  84.  
  85.  
  86. static external_methods_ptr methods; /* saved for access to error_exit */
  87.  
  88.  
  89. #ifdef MEM_STATS        /* optional extra stuff for statistics */
  90.  
  91. #define MALLOC_OVERHEAD  (SIZEOF(char *)) /* assumed overhead per request */
  92. #define MALLOC_FAR_OVERHEAD  (SIZEOF(char FAR *)) /* for "far" storage */
  93.  
  94. static long total_num_small = 0;    /* total # of small objects alloced */
  95. static long total_bytes_small = 0;    /* total bytes requested */
  96. static long cur_num_small = 0;        /* # currently alloced */
  97. static long max_num_small = 0;        /* max simultaneously alloced */
  98.  
  99. #ifdef NEED_FAR_POINTERS
  100. static long total_num_medium = 0;    /* total # of medium objects alloced */
  101. static long total_bytes_medium = 0;    /* total bytes requested */
  102. static long cur_num_medium = 0;        /* # currently alloced */
  103. static long max_num_medium = 0;        /* max simultaneously alloced */
  104. #endif
  105.  
  106. static long total_num_sarray = 0;    /* total # of sarray objects alloced */
  107. static long total_bytes_sarray = 0;    /* total bytes requested */
  108. static long cur_num_sarray = 0;        /* # currently alloced */
  109. static long max_num_sarray = 0;        /* max simultaneously alloced */
  110.  
  111. static long total_num_barray = 0;    /* total # of barray objects alloced */
  112. static long total_bytes_barray = 0;    /* total bytes requested */
  113. static long cur_num_barray = 0;        /* # currently alloced */
  114. static long max_num_barray = 0;        /* max simultaneously alloced */
  115.  
  116.  
  117. GLOBAL void
  118. j_mem_stats (void)
  119. {
  120.   /* since this is only a debugging stub, we can cheat a little on the
  121.    * trace message mechanism... helps 'cuz trace can't handle longs.
  122.    */
  123.   fprintf(stderr, "total_num_small = %ld\n", total_num_small);
  124.   fprintf(stderr, "total_bytes_small = %ld\n", total_bytes_small);
  125.   if (cur_num_small)
  126.     fprintf(stderr, "CUR_NUM_SMALL = %ld\n", cur_num_small);
  127.   fprintf(stderr, "max_num_small = %ld\n", max_num_small);
  128.   
  129. #ifdef NEED_FAR_POINTERS
  130.   fprintf(stderr, "total_num_medium = %ld\n", total_num_medium);
  131.   fprintf(stderr, "total_bytes_medium = %ld\n", total_bytes_medium);
  132.   if (cur_num_medium)
  133.     fprintf(stderr, "CUR_NUM_MEDIUM = %ld\n", cur_num_medium);
  134.   fprintf(stderr, "max_num_medium = %ld\n", max_num_medium);
  135. #endif
  136.   
  137.   fprintf(stderr, "total_num_sarray = %ld\n", total_num_sarray);
  138.   fprintf(stderr, "total_bytes_sarray = %ld\n", total_bytes_sarray);
  139.   if (cur_num_sarray)
  140.     fprintf(stderr, "CUR_NUM_SARRAY = %ld\n", cur_num_sarray);
  141.   fprintf(stderr, "max_num_sarray = %ld\n", max_num_sarray);
  142.   
  143.   fprintf(stderr, "total_num_barray = %ld\n", total_num_barray);
  144.   fprintf(stderr, "total_bytes_barray = %ld\n", total_bytes_barray);
  145.   if (cur_num_barray)
  146.     fprintf(stderr, "CUR_NUM_BARRAY = %ld\n", cur_num_barray);
  147.   fprintf(stderr, "max_num_barray = %ld\n", max_num_barray);
  148. }
  149.  
  150. #endif /* MEM_STATS */
  151.  
  152.  
  153. LOCAL void
  154. out_of_memory (int which)
  155. /* Report an out-of-memory error and stop execution */
  156. /* If we compiled MEM_STATS support, report alloc requests before dying */
  157. {
  158. #ifdef MEM_STATS
  159.   j_mem_stats();
  160. #endif
  161.   ERREXIT1(methods, "Insufficient memory (case %d)", which);
  162. }
  163.  
  164.  
  165.  
  166. METHODDEF void *
  167. alloc_small (size_t sizeofobject)
  168. /* Allocate a "small" (all-in-memory) object */
  169. {
  170.   void * result;
  171.  
  172. #ifdef MEM_STATS
  173.   total_num_small++;
  174.   total_bytes_small += sizeofobject + MALLOC_OVERHEAD;
  175.   cur_num_small++;
  176.   if (cur_num_small > max_num_small) max_num_small = cur_num_small;
  177. #endif
  178.  
  179.   result = malloc(sizeofobject);
  180.   if (result == NULL)
  181.     out_of_memory(1);
  182.   return result;
  183. }
  184.  
  185.  
  186. METHODDEF void
  187. free_small (void *ptr)
  188. /* Free a "small" (all-in-memory) object */
  189. {
  190.   free(ptr);
  191.  
  192. #ifdef MEM_STATS
  193.   cur_num_small--;
  194. #endif
  195. }
  196.  
  197.  
  198. #ifdef NEED_FAR_POINTERS
  199.  
  200. METHODDEF void FAR *
  201. alloc_medium (size_t sizeofobject)
  202. /* Allocate a "medium" (all in memory, but in far heap) object */
  203. {
  204.   void FAR * result;
  205.  
  206. #ifdef MEM_STATS
  207.   total_num_medium++;
  208.   total_bytes_medium += sizeofobject + MALLOC_FAR_OVERHEAD;
  209.   cur_num_medium++;
  210.   if (cur_num_medium > max_num_medium) max_num_medium = cur_num_medium;
  211. #endif
  212.  
  213.   result = far_malloc(sizeofobject);
  214.   if (result == NULL)
  215.     out_of_memory(2);
  216.   return result;
  217. }
  218.  
  219.  
  220. METHODDEF void
  221. free_medium (void FAR *ptr)
  222. /* Free a "medium" (all in memory, but in far heap) object */
  223. {
  224.   far_free(ptr);
  225.  
  226. #ifdef MEM_STATS
  227.   cur_num_medium--;
  228. #endif
  229. }
  230.  
  231. #endif /* NEED_FAR_POINTERS */
  232.  
  233.  
  234. METHODDEF JSAMPARRAY
  235. alloc_small_sarray (long samplesperrow, long numrows)
  236. /* Allocate a "small" (all-in-memory) 2-D sample array */
  237. {
  238.   JSAMPARRAY result;
  239. #ifdef BIG_MALLOCS_OK
  240.   JSAMPROW workspace;
  241. #endif
  242.   long i;
  243.  
  244. #ifdef MEM_STATS
  245.   total_num_sarray++;
  246. #ifdef BIG_MALLOCS_OK
  247.   total_bytes_sarray += numrows * samplesperrow * SIZEOF(JSAMPLE)
  248.             + MALLOC_FAR_OVERHEAD;
  249. #else
  250.   total_bytes_sarray += (samplesperrow * SIZEOF(JSAMPLE) + MALLOC_FAR_OVERHEAD)
  251.             * numrows;
  252. #endif
  253.   cur_num_sarray++;
  254.   if (cur_num_sarray > max_num_sarray) max_num_sarray = cur_num_sarray;
  255. #endif
  256.  
  257.   /* Get space for row pointers; this is always "near" on 80x86 */
  258.   result = (JSAMPARRAY) alloc_small((size_t) (numrows * SIZEOF(JSAMPROW)));
  259.  
  260.   /* Get the rows themselves; on 80x86 these are "far" */
  261.  
  262. #ifdef BIG_MALLOCS_OK
  263.   workspace = (JSAMPROW) far_malloc((size_t)
  264.                 (numrows * samplesperrow * SIZEOF(JSAMPLE)));
  265.   if (workspace == NULL)
  266.     out_of_memory(3);
  267.   for (i = 0; i < numrows; i++) {
  268.     result[i] = workspace;
  269.     workspace += samplesperrow;
  270.   }
  271. #else
  272.   for (i = 0; i < numrows; i++) {
  273.     result[i] = (JSAMPROW) far_malloc((size_t)
  274.                       (samplesperrow * SIZEOF(JSAMPLE)));
  275.     if (result[i] == NULL)
  276.       out_of_memory(3);
  277.   }
  278. #endif
  279.  
  280.   return result;
  281. }
  282.  
  283.  
  284. METHODDEF void
  285. free_small_sarray (JSAMPARRAY ptr, long numrows)
  286. /* Free a "small" (all-in-memory) 2-D sample array */
  287. {
  288.   /* Free the rows themselves; on 80x86 these are "far" */
  289. #ifdef BIG_MALLOCS_OK
  290.   far_free((void FAR *) ptr[0]);
  291. #else
  292.   long i;
  293.  
  294.   for (i = 0; i < numrows; i++) {
  295.     far_free((void FAR *) ptr[i]);
  296.   }
  297. #endif
  298.  
  299.   /* Free space for row pointers; this is always "near" on 80x86 */
  300.   free_small((void *) ptr);
  301.  
  302. #ifdef MEM_STATS
  303.   cur_num_sarray--;
  304. #endif
  305. }
  306.  
  307.  
  308. METHODDEF JBLOCKARRAY
  309. alloc_small_barray (long blocksperrow, long numrows)
  310. /* Allocate a "small" (all-in-memory) 2-D coefficient-block array */
  311. {
  312.   JBLOCKARRAY result;
  313. #ifdef BIG_MALLOCS_OK
  314.   JBLOCKROW workspace;
  315. #endif
  316.   long i;
  317.  
  318. #ifdef MEM_STATS
  319.   total_num_barray++;
  320. #ifdef BIG_MALLOCS_OK
  321.   total_bytes_barray += numrows * blocksperrow * SIZEOF(JBLOCK)
  322.             + MALLOC_FAR_OVERHEAD;
  323. #else
  324.   total_bytes_barray += (blocksperrow * SIZEOF(JBLOCK) + MALLOC_FAR_OVERHEAD)
  325.             * numrows;
  326. #endif
  327.   cur_num_barray++;
  328.   if (cur_num_barray > max_num_barray) max_num_barray = cur_num_barray;
  329. #endif
  330.  
  331.   /* Get space for row pointers; this is always "near" on 80x86 */
  332.   result = (JBLOCKARRAY) alloc_small((size_t) (numrows * SIZEOF(JBLOCKROW)));
  333.  
  334.   /* Get the rows themselves; on 80x86 these are "far" */
  335.  
  336. #ifdef BIG_MALLOCS_OK
  337.   workspace = (JBLOCKROW) far_malloc((size_t)
  338.                 (numrows * blocksperrow * SIZEOF(JBLOCK)));
  339.   if (workspace == NULL)
  340.     out_of_memory(4);
  341.   for (i = 0; i < numrows; i++) {
  342.     result[i] = workspace;
  343.     workspace += blocksperrow;
  344.   }
  345. #else
  346.   for (i = 0; i < numrows; i++) {
  347.     result[i] = (JBLOCKROW) far_malloc((size_t)
  348.                        (blocksperrow * SIZEOF(JBLOCK)));
  349.     if (result[i] == NULL)
  350.       out_of_memory(4);
  351.   }
  352. #endif
  353.  
  354.   return result;
  355. }
  356.  
  357.  
  358. METHODDEF void
  359. free_small_barray (JBLOCKARRAY ptr, long numrows)
  360. /* Free a "small" (all-in-memory) 2-D coefficient-block array */
  361. {
  362.   /* Free the rows themselves; on 80x86 these are "far" */
  363. #ifdef BIG_MALLOCS_OK
  364.   far_free((void FAR *) ptr[0]);
  365. #else
  366.   long i;
  367.  
  368.   for (i = 0; i < numrows; i++) {
  369.     far_free((void FAR *) ptr[i]);
  370.   }
  371. #endif
  372.  
  373.   /* Free space for row pointers; this is always "near" on 80x86 */
  374.   free_small((void *) ptr);
  375.  
  376. #ifdef MEM_STATS
  377.   cur_num_barray--;
  378. #endif
  379. }
  380.  
  381.  
  382.  
  383. /*
  384.  * About "big" array management:
  385.  *
  386.  * To allow machines with limited memory to handle large images,
  387.  * all processing in the JPEG system is done a few pixel or block rows
  388.  * at a time.  The above "small" array routines are only used to allocate
  389.  * strip buffers (as wide as the image, but just a few rows high).
  390.  * In some cases multiple passes must be made over the data.  In these
  391.  * cases the "big" array routines are used.  The array is still accessed
  392.  * a strip at a time, but the memory manager must save the whole array
  393.  * for repeated accesses.  The intended implementation is that there is
  394.  * a strip buffer in memory (as high as is possible given the desired memory
  395.  * limit), plus a backing file that holds the rest of the array.
  396.  *
  397.  * The request_big_array routines are told the total size of the image (in case
  398.  * it is useful to know the total file size that will be needed).  They are
  399.  * also given the unit height, which is the number of rows that will be
  400.  * accessed at once; the in-memory buffer should usually be made a multiple of
  401.  * this height for best efficiency.
  402.  *
  403.  * The request routines create control blocks (and may open backing files),
  404.  * but they don't create the in-memory buffers.  This is postponed until
  405.  * alloc_big_arrays is called.  At that time the total amount of space needed
  406.  * is known (approximately, anyway), so free memory can be divided up fairly.
  407.  *
  408.  * The access_big_array routines are responsible for making a specific strip
  409.  * area accessible (after reading or writing the backing file, if necessary).
  410.  * Note that the access routines are told whether the caller intends to modify
  411.  * the accessed strip; during a read-only pass this saves having to rewrite
  412.  * data to disk.
  413.  *
  414.  * The typical access pattern is one top-to-bottom pass to write the data,
  415.  * followed by one or more read-only top-to-bottom passes.  However, other
  416.  * access patterns may occur while reading.  For example, translation of image
  417.  * formats that use bottom-to-top scan order will require bottom-to-top read
  418.  * passes.  The memory manager need not support multiple write passes nor
  419.  * funny write orders (meaning that rearranging rows must be handled while
  420.  * reading data out of the big array, not while putting it in).
  421.  *
  422.  * In current usage, the access requests are always for nonoverlapping strips;
  423.  * that is, successive access start_row numbers always differ by exactly the
  424.  * unitheight.  This allows fairly simple buffer dump/reload logic if the
  425.  * in-memory buffer is made a multiple of the unitheight.  It would be
  426.  * possible to keep subsampled rather than fullsize data in the "big" arrays,
  427.  * thus reducing temp file size, if we supported overlapping strip access
  428.  * (access requests differing by less than the unitheight).  At the moment
  429.  * I don't believe this is worth the extra complexity.
  430.  *
  431.  * This particular implementation doesn't use temp files; the whole of a big
  432.  * array is allocated in (virtual) memory, and any swapping is done behind the
  433.  * scenes by the operating system.
  434.  */
  435.  
  436.  
  437.  
  438. /* The control blocks for virtual arrays.
  439.  * These are pretty minimal in this implementation.
  440.  * Note: in this implementation we could realize big arrays
  441.  * at request time and make alloc_big_arrays a no-op;
  442.  * however, doing it separately keeps callers honest.
  443.  */
  444.  
  445. struct big_sarray_control {
  446.     JSAMPARRAY mem_buffer;    /* memory buffer (the whole thing, here) */
  447.     long rows_in_mem;    /* Height of memory buffer */
  448.     long samplesperrow;    /* Width of memory buffer */
  449.     long unitheight;    /* # of rows accessed by access_big_sarray() */
  450.     big_sarray_ptr next;    /* list link for unrealized arrays */
  451. };
  452.  
  453. struct big_barray_control {
  454.     JBLOCKARRAY mem_buffer;    /* memory buffer (the whole thing, here) */
  455.     long rows_in_mem;    /* Height of memory buffer */
  456.     long blocksperrow;    /* Width of memory buffer */
  457.     long unitheight;    /* # of rows accessed by access_big_barray() */
  458.     big_barray_ptr next;    /* list link for unrealized arrays */
  459. };
  460.  
  461.  
  462. /* Headers of lists of control blocks for unrealized big arrays */
  463. static big_sarray_ptr unalloced_sarrays;
  464. static big_barray_ptr unalloced_barrays;
  465.  
  466.  
  467. METHODDEF big_sarray_ptr
  468. request_big_sarray (long samplesperrow, long numrows, long unitheight)
  469. /* Request a "big" (virtual-memory) 2-D sample array */
  470. {
  471.   big_sarray_ptr result;
  472.  
  473.   /* get control block */
  474.   result = (big_sarray_ptr) alloc_small(SIZEOF(struct big_sarray_control));
  475.  
  476.   result->mem_buffer = NULL;    /* lets access routine spot premature access */
  477.   result->rows_in_mem = numrows;
  478.   result->samplesperrow = samplesperrow;
  479.   result->unitheight = unitheight;
  480.   result->next = unalloced_sarrays; /* add to list of unallocated arrays */
  481.   unalloced_sarrays = result;
  482.  
  483.   return result;
  484. }
  485.  
  486.  
  487. METHODDEF big_barray_ptr
  488. request_big_barray (long blocksperrow, long numrows, long unitheight)
  489. /* Request a "big" (virtual-memory) 2-D coefficient-block array */
  490. {
  491.   big_barray_ptr result;
  492.  
  493.   /* get control block */
  494.   result = (big_barray_ptr) alloc_small(SIZEOF(struct big_barray_control));
  495.  
  496.   result->mem_buffer = NULL;    /* lets access routine spot premature access */
  497.   result->rows_in_mem = numrows;
  498.   result->blocksperrow = blocksperrow;
  499.   result->unitheight = unitheight;
  500.   result->next = unalloced_barrays; /* add to list of unallocated arrays */
  501.   unalloced_barrays = result;
  502.  
  503.   return result;
  504. }
  505.  
  506.  
  507. METHODDEF void
  508. alloc_big_arrays (long extra_small_samples, long extra_small_blocks,
  509.           long extra_medium_space)
  510. /* Allocate the in-memory buffers for any unrealized "big" arrays */
  511. /* 'extra' values are upper bounds for total future small-array requests */
  512. /* and far-heap requests */
  513. {
  514.   /* In this implementation we just malloc the whole arrays */
  515.   /* and expect the system's virtual memory to worry about swapping them */
  516.   big_sarray_ptr sptr;
  517.   big_barray_ptr bptr;
  518.  
  519.   for (sptr = unalloced_sarrays; sptr != NULL; sptr = sptr->next) {
  520.     sptr->mem_buffer = alloc_small_sarray(sptr->samplesperrow,
  521.                       sptr->rows_in_mem);
  522.   }
  523.  
  524.   for (bptr = unalloced_barrays; bptr != NULL; bptr = bptr->next) {
  525.     bptr->mem_buffer = alloc_small_barray(bptr->blocksperrow,
  526.                       bptr->rows_in_mem);
  527.   }
  528.  
  529.   unalloced_sarrays = NULL;    /* reset for possible future cycles */
  530.   unalloced_barrays = NULL;
  531. }
  532.  
  533.  
  534. METHODDEF JSAMPARRAY
  535. access_big_sarray (big_sarray_ptr ptr, long start_row, boolean writable)
  536. /* Access the part of a "big" sample array starting at start_row */
  537. /* and extending for ptr->unitheight rows.  writable is true if  */
  538. /* caller intends to modify the accessed area. */
  539. {
  540.   /* debugging check */
  541.   if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_mem ||
  542.       ptr->mem_buffer == NULL)
  543.     ERREXIT(methods, "Bogus access_big_sarray request");
  544.  
  545.   return ptr->mem_buffer + start_row;
  546. }
  547.  
  548.  
  549. METHODDEF JBLOCKARRAY
  550. access_big_barray (big_barray_ptr ptr, long start_row, boolean writable)
  551. /* Access the part of a "big" coefficient-block array starting at start_row */
  552. /* and extending for ptr->unitheight rows.  writable is true if  */
  553. /* caller intends to modify the accessed area. */
  554. {
  555.   /* debugging check */
  556.   if (start_row < 0 || start_row+ptr->unitheight > ptr->rows_in_mem ||
  557.       ptr->mem_buffer == NULL)
  558.     ERREXIT(methods, "Bogus access_big_barray request");
  559.  
  560.   return ptr->mem_buffer + start_row;
  561. }
  562.  
  563.  
  564. METHODDEF void
  565. free_big_sarray (big_sarray_ptr ptr)
  566. /* Free a "big" (virtual-memory) 2-D sample array */
  567. {
  568.   free_small_sarray(ptr->mem_buffer, ptr->rows_in_mem);
  569.   free_small((void *) ptr);    /* free the control block too */
  570. }
  571.  
  572.  
  573. METHODDEF void
  574. free_big_barray (big_barray_ptr ptr)
  575. /* Free a "big" (virtual-memory) 2-D coefficient-block array */
  576. {
  577.   free_small_barray(ptr->mem_buffer, ptr->rows_in_mem);
  578.   free_small((void *) ptr);    /* free the control block too */
  579. }
  580.  
  581.  
  582.  
  583. /*
  584.  * The method selection routine for virtual memory systems.
  585.  * The system-dependent setup routine should call this routine
  586.  * to install the necessary method pointers in the supplied struct.
  587.  */
  588.  
  589. GLOBAL void
  590. jselvirtmem (external_methods_ptr emethods)
  591. {
  592.   methods = emethods;        /* save struct addr for error exit access */
  593.  
  594.   emethods->alloc_small = alloc_small;
  595.   emethods->free_small = free_small;
  596. #ifdef NEED_FAR_POINTERS
  597.   emethods->alloc_medium = alloc_medium;
  598.   emethods->free_medium = free_medium;
  599. #endif
  600.   emethods->alloc_small_sarray = alloc_small_sarray;
  601.   emethods->free_small_sarray = free_small_sarray;
  602.   emethods->alloc_small_barray = alloc_small_barray;
  603.   emethods->free_small_barray = free_small_barray;
  604.   emethods->request_big_sarray = request_big_sarray;
  605.   emethods->request_big_barray = request_big_barray;
  606.   emethods->alloc_big_arrays = alloc_big_arrays;
  607.   emethods->access_big_sarray = access_big_sarray;
  608.   emethods->access_big_barray = access_big_barray;
  609.   emethods->free_big_sarray = free_big_sarray;
  610.   emethods->free_big_barray = free_big_barray;
  611.  
  612.   unalloced_sarrays = NULL;    /* make sure list headers are empty */
  613.   unalloced_barrays = NULL;
  614. }
  615.